package com.llyb.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.llyb.tingshu.album.client.TrackInfoFeignClient;
import com.llyb.tingshu.common.cache.TsCache;
import com.llyb.tingshu.common.constant.RedisConstant;
import com.llyb.tingshu.common.constant.SystemConstant;
import com.llyb.tingshu.common.rabbit.constant.MqConst;
import com.llyb.tingshu.common.rabbit.service.RabbitService;
import com.llyb.tingshu.common.result.Result;
import com.llyb.tingshu.model.album.TrackInfo;
import com.llyb.tingshu.model.user.*;
import com.llyb.tingshu.user.factory.StrategyFactory;
import com.llyb.tingshu.user.mapper.*;
import com.llyb.tingshu.user.service.UserInfoService;
import com.llyb.tingshu.user.strategy.ItemTypeStrategy;
import com.llyb.tingshu.vo.user.UserInfoVo;
import com.llyb.tingshu.vo.user.UserPaidRecordVo;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;

	@Autowired
	private WxMaService wxMaService;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private RabbitService rabbitService;

	@Autowired
	private UserPaidAlbumMapper userPaidAlbumMapper;

	@Autowired
	private UserPaidTrackMapper userPaidTrackMapper;

	@Autowired
	private TrackInfoFeignClient trackInfoFeignClient;

	@Autowired
	private VipServiceConfigMapper vipServiceConfigMapper;

	@Autowired
	private UserVipServiceMapper userVipServiceMapper;

	@Autowired
	private StrategyFactory strategyFactory;


	@Override
	public Map<String, Object> wxLogin(String code) {
		//  需要自己注入配置类
		WxMaJscode2SessionResult wxMaJscode2SessionResult = null;
		try {
			wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(code);
		} catch (WxErrorException e) {
			throw new RuntimeException(e);
		}

		String openid = wxMaJscode2SessionResult.getOpenid();

		// 判断需要注册还是登录
		UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().
				eq(UserInfo::getWxOpenId, openid));
		if (null == userInfo) {
			userInfo = new UserInfo();
			userInfo.setWxOpenId(openid);
			userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
			userInfo.setNickname("听友"+System.currentTimeMillis());

			userInfoMapper.insert(userInfo);

			// mq 异步实现用户账户的福利
			rabbitService.sendMessage(MqConst.EXCHANGE_USER, MqConst.ROUTING_USER_REGISTER, userInfo.getId());
		}

		// 返回登录信息
		String token = UUID.randomUUID().toString().replaceAll("-","");

		redisTemplate.opsForValue().set(RedisConstant.USER_LOGIN_KEY_PREFIX + token, userInfo,RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
		HashMap<String, Object> map = new HashMap<>();
		map.put("token", token);
		return map;
	}

	@TsCache(prefix = "user:info:")
	@Override
	public UserInfoVo getUserInfo(Long userId) {

		UserInfo userInfo = userInfoMapper.selectById(userId);

		UserInfoVo userInfoVo = new UserInfoVo();
		BeanUtils.copyProperties(userInfo, userInfoVo);
		return userInfoVo;
	}

	@Override
	public Map<Long, Integer> userIsPaidTrack(Long albumId, List<Long> trackIdList, Long userId) {

		/**
		 * 		用户购买了这个声音 map.put(trackId,1)
		 *
		 * 1. 查询用户是否购买了专辑
		 * 		若是：
		 * 		返回所有都是 1
		 * 2. 查询用户购买了哪些声音
		 *
		 */
		// 查询用户是否购买了专辑
		UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>()
				.eq(UserPaidAlbum::getUserId, userId)
				.eq(UserPaidAlbum::getAlbumId, albumId));

		// 默认都是未购买
		Map<Long, Integer> map = trackIdList.stream().collect(Collectors.toMap(id -> id, id -> 0));

		if (null != userPaidAlbum) {
			map.forEach((id, value) -> map.put(id, 1));
			return map;
		}

		// 查询用户购买了哪些声音
		List<UserPaidTrack> paidTrackIdList = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>()
				.eq(UserPaidTrack::getUserId, userId)
				.in(UserPaidTrack::getTrackId, trackIdList));

		paidTrackIdList.forEach(paidTrack -> map.put(paidTrack.getTrackId(), 1));

		return map;
	}

	@Override
	public Boolean isPaidAlbum(Long userId, Long albumId) {

		return userPaidAlbumMapper.selectCount(new LambdaQueryWrapper<UserPaidAlbum>()
				.eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId)) > 0 ;

	}

	@Override
	public List<Long> findUserPaidTrackList(Long albumId, Long userId) {

		List<UserPaidTrack> paidTrackIdList = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>()
				.eq(UserPaidTrack::getUserId, userId)
				.eq(UserPaidTrack::getAlbumId, albumId));
		List<Long> collect = paidTrackIdList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());

		return collect;
	}

	@Override
	public void updateUser(UserInfoVo userInfoVo) {

		UserInfo userInfo = new UserInfo();
		BeanUtils.copyProperties(userInfoVo, userInfo);
		userInfoMapper.updateById(userInfo);

	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void savePaidRecord(UserPaidRecordVo userPaidRecordVo) {

		ItemTypeStrategy itemTypeStrategy = strategyFactory.getStrategy(userPaidRecordVo.getItemType());
		itemTypeStrategy.savePaidRecord(userPaidRecordVo);

		/*// 使用工厂模式+策略模式
		*//**
		 * 1 判断类型
		 * 	1.1 专辑
		 * 	1.2 声音
		 * 	1.3 vip
		 *//*
		if (userPaidRecordVo.getItemType().equals(SystemConstant.ORDER_ITEM_TYPE_ALBUM)) {
			// 防止添加重复数据
			if (userPaidAlbumMapper.selectCount(new LambdaQueryWrapper<UserPaidAlbum>()
					.eq(UserPaidAlbum::getUserId, userPaidRecordVo.getUserId())
					.eq(UserPaidAlbum::getAlbumId, userPaidRecordVo.getItemIdList().get(0)))>0){
				return;
			}
			// 专辑
			UserPaidAlbum userPaidAlbum = new UserPaidAlbum();
			userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
			userPaidAlbum.setAlbumId(userPaidRecordVo.getItemIdList().get(0));
			userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
			userPaidAlbumMapper.insert(userPaidAlbum);
		}else if (userPaidRecordVo.getItemType().equals(SystemConstant.ORDER_ITEM_TYPE_TRACK)) {
			List<Long> itemIdList = userPaidRecordVo.getItemIdList();
			// 防止添加重复数据
			LambdaQueryWrapper<UserPaidTrack> wrapper = new LambdaQueryWrapper<>();
			wrapper.eq(UserPaidTrack::getUserId, userPaidRecordVo.getUserId());
			wrapper.in(UserPaidTrack::getTrackId, itemIdList);
			List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(wrapper);
			// 找出所有存在的
			Set<Long> paidTrackIdSet = userPaidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toSet());
			if (!CollectionUtils.isEmpty(userPaidTrackList)){
				// 找出所有存在的，利用mq增加余额
				ArrayList<Long> roolbackTrackIdList = new ArrayList<>();
				for (Long trackId : itemIdList) {
					if (paidTrackIdSet.contains(trackId)) {
						roolbackTrackIdList.add(trackId);
					}
				}
				// 发送消息，恢复余额
				// todo 恢复余额的监听队列
				rabbitService.sendMessage(MqConst.EXCHANGE_ORDER, MqConst.ROUTING_ACCOUNT_COMPENSATION, roolbackTrackIdList);
			}
			// 获取声音对象，为了获取专辑id
			Result<TrackInfo> trackInfoR = trackInfoFeignClient.getTrackInfo(itemIdList.get(0));
			Assert.notNull(trackInfoR, "获取声音信息失败");
			TrackInfo trackInfo = trackInfoR.getData();
			// 声音
			for (Long trackId : itemIdList) {
				UserPaidTrack userPaidTrack = new UserPaidTrack();
				userPaidTrack.setUserId(userPaidRecordVo.getUserId());
				userPaidTrack.setTrackId(trackId);
				userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
				userPaidTrack.setAlbumId(trackInfo.getAlbumId());
				userPaidTrackMapper.insert(userPaidTrack);
			}
		}else {
			// vip会员  判断是否已经是会员，续期或新增
			UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
			Date currentDate = new Date();
			UserVipService userVipService = new UserVipService();
			userVipService.setUserId(userPaidRecordVo.getUserId());
			userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
			userVipService.setStartTime(currentDate);

			if (userInfo.getIsVip() == 1 && userInfo.getVipExpireTime().after(currentDate)) {
				currentDate = userInfo.getVipExpireTime();
			}*//*else {
			}*//*
			// 购买的月数
			VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(userPaidRecordVo.getItemIdList().get(0));
			Integer serviceMonth = vipServiceConfig.getServiceMonth();
			LocalDateTime currentDateTime = new LocalDateTime(currentDate);
			Date expireTime = currentDateTime.plusMonths(serviceMonth).toDate();

			userVipService.setExpireTime(expireTime);
			userVipServiceMapper.insert(userVipService);

			userInfo.setIsVip(1);
			userInfo.setVipExpireTime(expireTime);
			userInfoMapper.updateById(userInfo);

		}*/
	}
}
